package com.yh.csx.bsf.flow.engine.api;

import com.fasterxml.jackson.core.type.TypeReference;
import com.sun.mail.util.MailSSLSocketFactory;
import com.yh.csx.bsf.core.util.ContextUtils;
import com.yh.csx.bsf.core.util.JsonUtils;
import com.yh.csx.bsf.core.util.StringUtils;
import com.yh.csx.bsf.flow.core.FlowProperties;
import com.yh.csx.bsf.flow.core.base.Model;
import com.yh.csx.bsf.flow.core.base.Variable;
import com.yh.csx.bsf.flow.core.db.ConvertUtil;
import com.yh.csx.bsf.flow.engine.state.StateEngineException;
import com.yh.csx.bsf.message.sms.SmsProvider;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import lombok.var;
import javax.script.Invocable;
import javax.script.ScriptEngineManager;
import java.util.*;

import javax.mail.*;
import javax.mail.internet.*;


/**
 * @author: chejiangyi
 * @version: 2019-10-24 15:13
 **/
@Slf4j
public class CommonApi {
    public static Object runJs(int flowid,String code){
        try {
            ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
            code = "function run(){ "+code+"}";
            val engine = scriptEngineManager.getEngineByName("javascript");
            code=code.replaceAll("\r\n", " "); code=code.replaceAll("\n", " ");code=code.replaceAll("\r", " ");
            engine.eval(code);
            Invocable invokeEngine = (Invocable)engine;
            return invokeEngine.invokeFunction("run");
        }catch (Exception exp){
            throw new StateEngineException(flowid,"js动态脚本出错:"+code,exp);
        }
    }

    public static void doScript(Integer flowId,Integer taskId,String route,String code,Map<String,Variable> flowVariables){
        code = Api.run(flowId,taskId,code,flowVariables);
        code = "var param={};var route='"+route+"';"+code+" return param;";
        code=code.replaceAll("\r\n", " "); code=code.replaceAll("\n", " ");code=code.replaceAll("\r", " ");
        val map = runJs(flowId,code);
        String json = JsonUtils.serialize(map);
        val resultMap = JsonUtils.deserialize(json, new TypeReference<HashMap<String,String>>(){});
        for(val kv : resultMap.entrySet()){
            var variable = flowVariables.get(kv.getKey());
            if(variable!=null){
                variable.setValue(kv.getValue());
            }else{
                variable = new Variable(kv.getKey(),kv.getValue(),"js动态添加的变量");
            }
            flowVariables.put(kv.getKey(),variable);
        }
    }

//    public static List<Model.RouteResult> route(String code, List<String> results,Map<String,Variable> flowVariables){
//        code = Api.run(code,flowVariables);
//        code = Api.num(code,results);
//        code = ConvertUtil.objToStr(runJs(code));
//        return results(code);
//    }

    public static String routeStr(int flowid,int taskid, List<Model.Route> routes, List<String> results, Map<String,Variable> flowVariables){
        var routeResults = new ArrayList<String>();
        for(var route:routes) {
            var bool=false;
            var code=route.getScript();
            if(StringUtils.isEmpty(code)){
                bool=true;
            }else {
                code = Api.run(flowid,taskid, code, flowVariables);
                code = Api.num(flowid, code, results);
                //表达式支持+js代码支持
                if(!code.contains("return ")){
                    code = "return "+code +";";
                }
                var r = runJs(flowid, code);
                if(r!=null&&r instanceof String){
                    if("true".equalsIgnoreCase((String)r)){
                        bool =true;
                    }
                }else {
                    bool = ConvertUtil.objToBool(r);
                }
            }
            if (bool == true) {
                routeResults.add(route.getNext());
            }
        }
        var rs = String.join(",",routeResults);
        return rs;
    }

    private static List<Model.RouteResult> results(String result){
        List<Model.RouteResult> rs = new ArrayList<>();
        if(result!=null) {
            var nodes = result.split(",");
            Arrays.stream(nodes).forEach(c->{
                var r=c;var t="";
                if(c.contains("(")&&c.contains(")")){
                   var title = c.substring(c.indexOf('('),c.indexOf(')')).replace("(","").replace(")","");
                   r = r.replace("("+title+")","");
                   t=title;
                }
                Model.RouteResult routeResult = new Model.RouteResult();
                routeResult.setNode(r);routeResult.setTitle(t);
                rs.add(routeResult);
            });
        }
        return rs;
    }

    public static List<Model.RouteResult> routeToNodes(List<Model.Route> routes){
        List<Model.RouteResult> rs = new ArrayList<>();
        for(var route:routes) {
            rs.add(new Model.RouteResult(route.getNext(),route.getTitle()));
        }
        return rs;
    }



    
    public static void sms(int flowid,String userno,String message){
        try {
            val p = ContextUtils.getBean(FlowProperties.class,false);
            if(p.getSms()) {
                val provider = ContextUtils.getBean(SmsProvider.class, false);
                if (provider != null) {
                    val userInfo = UserApi.getUser(userno);
                    provider.sendText(userInfo.getMobile(), message);
                } else {
                    throw new StateEngineException(flowid,"短息开关未打开");
                }
            }
            log.info("发送短信:"+userno+" message:"+message);
        }catch (Exception e){
            throw new StateEngineException(flowid,"短信发送失败",e);
        }
    }

    public static void mail(int flowid,String userno,String subject,String msg){
        try {
            val p = ContextUtils.getBean(FlowProperties.class,false);
            if(p.getMail()) {
                val userInfo = UserApi.getUser(userno);
                // 发件人电子邮箱
                final String from = p.getMailfrom();//"csx_marketing@yonghui.cn";
                // 发件人电子邮箱密码
                final String pass = p.getMailpass();// "yh601933";
                // 指定发送邮件的主机为 smtp.qq.com
                String host = p.getMailhost();// "smtp.yonghui.cn";
                // 获取系统属性
                Properties properties = System.getProperties();
                // 设置邮件服务器
                properties.setProperty("mail.smtp.host", host);
                properties.put("mail.smtp.auth", "true");
                MailSSLSocketFactory sf = new MailSSLSocketFactory();
                sf.setTrustAllHosts(true);
                properties.put("mail.smtp.ssl.enable", "true");
                properties.put("mail.smtp.ssl.socketFactory", sf);
                // 获取默认session对象
                Session session = Session.getInstance(properties, new Authenticator() {
                    // qq邮箱服务器账户、第三方登录授权码
                    @Override
                    public PasswordAuthentication getPasswordAuthentication() {
                        // 发件人邮件用户名、密码
                        return new PasswordAuthentication(from, pass);
                    }
                });
                /**
                 Session session = Session.getDefaultInstance(properties, new Authenticator() {
                 public PasswordAuthentication getPasswordAuthentication() { // qq邮箱服务器账户、第三方登录授权码
                 return new PasswordAuthentication(from, pass); // 发件人邮件用户名、密码
                 }
                 });
                 **/
                // 创建默认的 MimeMessage 对象
                MimeMessage message = new MimeMessage(session);
                // Set From: 头部头字段
                message.setFrom(new InternetAddress(from));
                // Set To: 头部头字段 接收人邮箱
                message.addRecipient(Message.RecipientType.TO, new InternetAddress(userInfo.getEmail()));
                // Set Subject: 主题文字
                //String  subject ="办公流程通知";
                message.setSubject(subject);
                // 创建消息部分
                BodyPart messageBodyPart = new MimeBodyPart();
                // 消息
                // MiniMultipart类是一个容器类，包含MimeBodyPart类型的对象
                Multipart mainPart = new MimeMultipart();
                // 创建一个包含HTML内容的MimeBodyPart
                BodyPart html = new MimeBodyPart();
                // 设置HTML内容
                html.setContent(msg, "text/html; charset=utf-8");
                mainPart.addBodyPart(html);
                // 将MiniMultipart对象设置为邮件内容
                messageBodyPart.setContent(mainPart);
                // 创建多重消息
                Multipart multipart = new MimeMultipart();
                // 设置文本消息部分
                multipart.addBodyPart(messageBodyPart);
                // 发送完整消息
                message.setContent(multipart);
                // 发送消息
                Transport.send(message);
            }
            log.info("发送邮件:"+userno+" subject:"+subject+" message:"+msg);
        }catch (Exception e){
            throw new StateEngineException(flowid,"邮件发送失败",e);
        }
    }

    public static  <T> void random(List<T> list) {
        int size = list.size();
        Random random = new Random(UUID.randomUUID().hashCode());
        for(int i = 0; i < size; i++) {
            int randomPos = random.nextInt(size);
            T temp = list.get(i);
            list.set(i, list.get(randomPos));
            list.set(randomPos, temp);
        }
    }

    public static Map<String,Variable> filterSystemChar(Collection<Variable> variables){
        Map<String,Variable> rs = new HashMap<>();
        if(variables!=null) {
            for (var variable : variables) {
                var v = new Variable(filterSystemChar(variable.getKey()),filterSystemChar(variable.getValue()),"");
                rs.put(v.getKey(),v);
            }
        }
        return rs;
    }

    private static String filterSystemChar(String str){
        if(str!=null) {
            str = str.replace("【", "");
            str = str.replace("】", "");
            str = str.replace("〖", "");
            str = str.replace("〗", "");
        }
        return str;
    }
}
